package com.ssy.lingxi.order.serviceimpl.base;

import com.querydsl.core.group.GroupBy;
import com.querydsl.core.types.Projections;
import com.querydsl.jpa.impl.JPAQuery;
import com.querydsl.jpa.impl.JPAQueryFactory;
import com.ssy.lingxi.common.constant.order.OrderSourceKindEnum;
import com.ssy.lingxi.common.constant.order.OrderTypeEnum;
import com.ssy.lingxi.common.response.ResponseCode;
import com.ssy.lingxi.common.response.Wrapper;
import com.ssy.lingxi.order.entity.*;
import com.ssy.lingxi.order.model.constant.*;
import com.ssy.lingxi.order.model.dto.MobileOrderPageDTO;
import com.ssy.lingxi.order.model.dto.MobileOrderProductQueryDTO;
import com.ssy.lingxi.order.model.dto.MobileOrderQueryDTO;
import com.ssy.lingxi.order.model.vo.mobile.response.*;
import com.ssy.lingxi.order.service.base.IBaseMobileOrderService;
import com.ssy.lingxi.order.utils.NumberUtil;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

/**
 * App - 基础订单服务接口实现类
 * @author 万宁
 * @version 2.0.0
 * @date 2021-09-22
 */
@Service
public class BaseMobileOrderServiceImpl implements IBaseMobileOrderService {
    @Resource
    private JPAQueryFactory jpaQueryFactory;

    /**
     * 订单是否没有被取消或没有被中止
     * @param query 订单查询DTO
     * @return true-没有被取消或中止，false-已经被取消或中止
     */
    @Override
    public Boolean notCancelledOrTerminated(MobileOrderQueryDTO query) {
        return !query.getInnerStatus().equals(BuyerInnerStatusEnum.CANCELLED.getCode()) && !query.getInnerStatus().equals(BuyerInnerStatusEnum.TERMINATED.getCode()) && !query.getOuterStatus().equals(OrderOuterStatusEnum.CANCELLED.getCode()) && !query.getOuterStatus().equals(OrderOuterStatusEnum.TERMINATED.getCode());
    }

    /**
     * 订单是否能调整送货时间
     * @param query 订单查询DTO
     * @return true-是， false-否
     */
    @Override
    public Boolean canBuyerModifyDeliverTime(MobileOrderQueryDTO query) {
        //订单状态不为已完成，已取消，已中止且未发货过
        return !(query.getOuterStatus().equals(OrderOuterStatusEnum.ACCOMPLISHED.getCode()) || query.getOuterStatus().equals(OrderOuterStatusEnum.CANCELLED.getCode()) || query.getOuterStatus().equals(OrderOuterStatusEnum.TERMINATED.getCode()) || query.getHasDelivered());
    }

    /**
     * 订单是否能退款
     * @param query 订单查询DTO
     * @return true-是， false-否
     */
    @Override
    public Boolean canBuyerRefundOrder(MobileOrderQueryDTO query) {
        //退款条件：订单为拼团订单，外部状态为“已取消”，退款失败，支付记录包含一次100%支付的记录
        return query.getOrderKind().equals(OrderSourceKindEnum.GROUP.getCode()) && query.getOuterStatus().equals(OrderOuterStatusEnum.CANCELLED.getCode()) && !query.getHasRefund() && query.getCanRefund();
    }

    /**
     * 订单是否能“售后”
     * @param query 订单查询DTO
     * @return 是-true，否-false
     */
    @Override
    public Boolean canOrderAfterSale(MobileOrderQueryDTO query) {
        //如果是拼团订单：（拼团状态为拼团失败，且订单的外部状态为“待确认发货”）或（拼团成功）， 则可以售后
        //如果非拼团订单：已经有收到款或有发货的订单即显示售后按钮（包括状态为已中止的订单）
        return query.getOrderKind().equals(OrderSourceKindEnum.GROUP.getCode()) ? (((query.getOuterStatus().equals(OrderOuterStatusEnum.TO_CONFIRM_DELIVERY.getCode()) && query.getPromotionStatus().equals(OrderPromotionStatusEnum.GROUP_FAILED.getCode()))) || query.getPromotionStatus().equals(OrderPromotionStatusEnum.GROUP_SUCCESS.getCode())) : (query.getHasPaid() || query.getHasDelivered());
    }

    /**
     * 订单是否能“归档”
     * @param query 订单查询DTO
     * @return 是-true，否-false
     */
    @Override
    public Boolean canOrderArchive(MobileOrderQueryDTO query) {
        return notCancelledOrTerminated(query) && query.getInnerStatus().equals(BuyerInnerStatusEnum.BUYER_TO_ARCHIVE.getCode());
    }

    /**
     * 订单是否能“再次购买”
     * @param query 订单查询DTO
     * @return 是-true，否-false
     */
    @Override
    public Boolean canOrderAgain(MobileOrderQueryDTO query) {
        return notCancelledOrTerminated(query) && (query.getInnerStatus().equals(BuyerInnerStatusEnum.ACCOMPLISHED.getCode()) || query.getOuterStatus().equals(OrderOuterStatusEnum.ACCOMPLISHED.getCode())) && !OrderTypeEnum.CREDITS_EXCHANGE.getCode().equals(query.getOrderType());
    }

    /**
     * 订单是否能“取消”
     * @param query 订单查询DTO
     * @return 是-true，否-false
     */
    @Override
    public Boolean canOrderCancel(MobileOrderQueryDTO query) {
        //拼团订单“拼团中”时，不能取消或中止
        if (query.getOrderKind().equals(OrderSourceKindEnum.GROUP.getCode()) && (query.getPromotionStatus().equals(OrderPromotionStatusEnum.GROUPING.getCode()) || query.getPromotionStatus().equals(OrderPromotionStatusEnum.GROUP_WAITING_CONFIRM.getCode()))) {
            return false;
        }

        //支付中的订单不能取消
        if (query.getInnerStatus().equals(BuyerInnerStatusEnum.BUYER_PAYING.getCode())) {
            return false;
        }

        //待归档与已完成订单不能取消或中止订单
        if (query.getHasPaid() || query.getInnerStatus().equals(BuyerInnerStatusEnum.BUYER_TO_ARCHIVE.getCode()) || query.getInnerStatus().equals(BuyerInnerStatusEnum.ACCOMPLISHED.getCode()) || query.getOuterStatus().equals(OrderOuterStatusEnum.ACCOMPLISHED.getCode())) {
            return false;
        } else if (query.getInnerStatus().equals(BuyerInnerStatusEnum.BUYER_TO_SUBMIT_VALIDATE.getCode()) || query.getInnerStatus().equals(BuyerInnerStatusEnum.BUYER_TO_SUBMIT.getCode())) {
            //刚创建完毕，没有提交内部审核，没有提交到供应商，显示取消按钮
            return true;
        } else {
            //未签署电子合同且从未收到款且未发过货的订单，显示取消订单按钮
            return !query.getHasPaid() && !query.getHasDelivered() && !query.getOuterStatus().equals(OrderOuterStatusEnum.CANCELLED.getCode()) && NumberUtil.isNullOrZero(query.getContractId());
        }
    }

    /**
     * 订单是否能“评论”
     * @param query 订单查询DTO
     * @return 是-true，否-false
     */
    @Override
    public Boolean canOrderComment(MobileOrderQueryDTO query) {
        return notCancelledOrTerminated(query) && !query.getBuyerCommented() && (query.getInnerStatus().equals(BuyerInnerStatusEnum.ACCOMPLISHED.getCode()) || query.getOuterStatus().equals(OrderOuterStatusEnum.ACCOMPLISHED.getCode()));
    }

    /**
     * 订单是否能“确认电子合同”
     * @param query 订单查询DTO
     * @return 是-true，否-false
     */
    @Override
    public Boolean canOrderConfirmContract(MobileOrderQueryDTO query) {
        return notCancelledOrTerminated(query) && query.getInnerStatus().equals(BuyerInnerStatusEnum.BUYER_TO_CONFIRM_CONTRACT.getCode());
    }

    /**
     * 订单是否能“确认采购收货单”
     * @param query 订单查询DTO
     * @return 是-true，否-false
     */
    @Override
    public Boolean canOrderConfirmReception(MobileOrderQueryDTO query) {
        return notCancelledOrTerminated(query) && query.getInnerStatus().equals(BuyerInnerStatusEnum.BUYER_TO_VALIDATE_DEPOT.getCode());
    }

    /**
     * 订单是否能“新增采购收货单”
     * @param query 订单查询DTO
     * @return 是-true，否-false
     */
    @Override
    public Boolean canOrderCreateReception(MobileOrderQueryDTO query) {
        return notCancelledOrTerminated(query) && query.getInnerStatus().equals(BuyerInnerStatusEnum.BUYER_TO_DEPOSIT.getCode());
    }

    /**
     * 订单是否能“支付”
     * @param query 订单查询DTO
     * @return 是-true，否-false
     */
    @Override
    public Boolean canOrderPay(MobileOrderQueryDTO query) {
        //“待支付订单” 的 状态：“未支付”、“支付失败”、“支付成功，但被供应商确认未到账”
        return notCancelledOrTerminated(query) && (query.getInnerStatus().equals(BuyerInnerStatusEnum.BUYER_TO_PAY.getCode()) || query.getInnerStatus().equals(BuyerInnerStatusEnum.BUYER_PAY_FAIL.getCode()) || (query.getInnerStatus().equals(BuyerInnerStatusEnum.BUYER_PAY_SUCCESS.getCode()) && query.getOuterStatus().equals(OrderOuterStatusEnum.PAYMENT_NOT_ACCOMPLISH.getCode())));
    }

    /**
     * 订单是否能“确认收货”
     * @param query 订单查询DTO
     * @return 是-true，否-false
     */
    @Override
    public Boolean canOrderReceive(MobileOrderQueryDTO query) {
        return notCancelledOrTerminated(query) && query.getInnerStatus().equals(BuyerInnerStatusEnum.BUYER_TO_RECEIVE.getCode());
    }

    /**
     * 订单是否能“提交”
     * @param query 订单查询DTO
     * @return 是-true，否-false
     */
    @Override
    public Boolean canOrderSubmit(MobileOrderQueryDTO query) {
        return notCancelledOrTerminated(query) && query.getInnerStatus().equals(BuyerInnerStatusEnum.BUYER_TO_SUBMIT.getCode());
    }

    /**
     * 订单是否能“一级审核”
     * @param query 订单查询DTO
     * @return 是-true，否-false
     */
    @Override
    public Boolean canOrderValidateGradeOne(MobileOrderQueryDTO query) {
        return notCancelledOrTerminated(query) && query.getInnerStatus().equals(BuyerInnerStatusEnum.BUYER_VALIDATE_GRADE_ONE.getCode());
    }

    /**
     * 订单是否能“二级审核”
     * @param query 订单查询DTO
     * @return 是-true，否-false
     */
    @Override
    public Boolean canOrderValidateGradeTwo(MobileOrderQueryDTO query) {
        return notCancelledOrTerminated(query) && query.getInnerStatus().equals(BuyerInnerStatusEnum.BUYER_VALIDATE_GRADE_TWO.getCode());
    }

    /**
     * 判断采购商是否能删除订单
     * @param query 订单查询DTO
     * @return true-是，false-否
     */
    @Override
    public Boolean canBuyerDeleteOrder(MobileOrderQueryDTO query) {
        //删除条件：除拼团订单且订单外部状态为”已取消“且拼团退款失败的订单外，显示”删除“按钮
        return !query.getOrderKind().equals(OrderSourceKindEnum.GROUP.getCode()) && query.getOuterStatus().equals(OrderOuterStatusEnum.CANCELLED.getCode());
    }

    /**
     * 分页查询采购订单
     * @param buyerMemberId    采购会员Id
     * @param buyerRoleId      采购会员角色Id
     * @param keyword          订单编号/供应会员/订单摘要
     * @param buyerInnerStatus 采购会员内部状态
     * @param outerStatus      订单外部状态
     * @param current          当前页
     * @param pageSize         每页行数
     * @return 查询结果
     */
    @Override
    public MobileOrderPageDTO pageMobileBuyerOrders(Long buyerMemberId, Long buyerRoleId, String keyword, Integer buyerInnerStatus, Integer outerStatus, int current, int pageSize) {
        return pageMobileBuyerOrders(buyerMemberId, buyerRoleId, keyword, "", "", buyerInnerStatus, outerStatus, current, pageSize);
    }

    /**
     * 分页查询采购订单
     * @param buyerMemberId    采购会员Id
     * @param buyerRoleId      采购会员角色Id
     * @param keyword          订单编号/供应会员/订单摘要
     * @param startDate        订单起始日期
     * @param endDate          订单结束日期
     * @param buyerInnerStatus 采购会员内部状态
     * @param outerStatus      订单外部状态
     * @param current          当前页
     * @param pageSize         每页行数
     * @return 查询结果
     */
    @Override
    public MobileOrderPageDTO pageMobileBuyerOrders(Long buyerMemberId, Long buyerRoleId, String keyword, String startDate, String endDate, Integer buyerInnerStatus, Integer outerStatus, int current, int pageSize) {
        QOrderDO qOrder = QOrderDO.orderDO;
        QOrderProductDO qOrderProduct = QOrderProductDO.orderProductDO;
        QOrderContractDO qOrderContract = QOrderContractDO.orderContractDO;

        //Step 1: 首先分页查询订单表与其一对一关联的表（这样才可以分页）。不查询Srm订单和请购单订单
        JPAQuery<MobileOrderQueryDTO> query = jpaQueryFactory
                .selectDistinct(Projections.constructor(MobileOrderQueryDTO.class, qOrder.shopId, qOrder.id, qOrder.orderNo, qOrder.orderMode, qOrder.orderKind, qOrder.vendorMemberId, qOrder.vendorRoleId, qOrder.vendorMemberName, qOrder.vendorLogo, qOrder.totalAmount, qOrder.buyerInnerStatus, qOrder.outerStatus, qOrder.buyerCommented, qOrder.hasPaid, qOrder.hasDelivered, qOrderContract.contractId, qOrder.promotionStatus, qOrder.groupId, qOrder.canRefund, qOrder.hasRefund, qOrder.orderType))
                .from(qOrder)
                .leftJoin(qOrderProduct).on(qOrder.id.eq(qOrderProduct.order.id))
                .leftJoin(qOrderContract).on(qOrder.id.eq(qOrderContract.order.id))
                .where(qOrder.buyerMemberId.eq(buyerMemberId).and(qOrder.buyerRoleId.eq(buyerRoleId)))
                .where(qOrder.orderKind.ne(OrderSourceKindEnum.SRM.getCode()).and(qOrder.orderKind.ne(OrderSourceKindEnum.REQUISITION.getCode())));

        //Step 2: 构造查询条件
        if (StringUtils.hasLength(keyword)) {
            String pattern = "%".concat(keyword.trim()).concat("%");
            query.where(qOrder.orderNo.like(pattern).or(qOrder.vendorMemberName.like(pattern)).or(qOrderProduct.name.like(pattern)));
        }

        //订单起始时间
        if (StringUtils.hasLength(startDate)) {
            query.where(qOrder.createTime.after(LocalDateTime.parse(startDate.concat(" 00:00:00"), OrderServiceContants.DEFAULT_TIME_FORMATTER)));
        }

        //订单起始时间
        if (StringUtils.hasLength(endDate)) {
            query.where(qOrder.createTime.before(LocalDateTime.parse(endDate.concat(" 23:59:59"), OrderServiceContants.DEFAULT_TIME_FORMATTER)));
        }

        //采购商内部状态
        if (NumberUtil.notNullAndPositive(buyerInnerStatus)) {
            query.where(qOrder.buyerInnerStatus.eq(buyerInnerStatus));
        }

        //外部状态
        if (NumberUtil.notNullAndPositive(outerStatus)) {
            query.where(qOrder.outerStatus.eq(outerStatus));
        }

        //Step 3: 倒序排序、分页、总数
        long totalCount = query.fetchCount();
        query.orderBy(qOrder.id.desc());
        query.limit(pageSize).offset((current - 1) * pageSize);

        List<MobileOrderQueryDTO> orders = query.fetch();

        //Step 4: 再查询订单商品表
        List<MobileOrderProductQueryDTO> orderProducts = jpaQueryFactory
                .select(Projections.constructor(MobileOrderProductQueryDTO.class,
                        qOrderProduct.order.id,
                        qOrderProduct.id,
                        qOrderProduct.productId,
                        qOrderProduct.skuId,
                        qOrderProduct.stockId,
                        qOrderProduct.priceType,
                        qOrderProduct.logo,
                        qOrderProduct.name,
                        qOrderProduct.category,
                        qOrderProduct.brand,
                        qOrderProduct.spec,
                        qOrderProduct.unit,
                        qOrderProduct.refPrice,
                        qOrderProduct.quantity,
                        qOrderProduct.deliverType,
                        qOrderProduct.address,
                        qOrderProduct.receiver,
                        qOrderProduct.phone
                )).from(qOrderProduct).where(qOrderProduct.order.id.in(orders.stream().map(MobileOrderQueryDTO::getOrderId).collect(Collectors.toList())))
                .fetch();

        //拼接订单商品
        orders.forEach(order -> order.setProducts(orderProducts.stream().filter(orderProduct -> orderProduct.getOrderId().equals(order.getOrderId())).collect(Collectors.toList())));

        return new MobileOrderPageDTO(totalCount, orders);
    }

    /**
     * 分页查询“待支付”的采购订单
     * @param buyerMemberId 采购会员Id
     * @param buyerRoleId   采购会员角色Id
     * @param keyword       订单编号/供应会员/订单摘要
     * @param current       当前页
     * @param pageSize      每页行数
     * @return 查询结果
     */
    @Override
    public MobileOrderPageDTO pageMobileToPayOrders(Long buyerMemberId, Long buyerRoleId, String keyword, int current, int pageSize) {
        QOrderDO qOrder = QOrderDO.orderDO;
        QOrderProductDO qOrderProduct = QOrderProductDO.orderProductDO;
        QOrderContractDO qOrderContract = QOrderContractDO.orderContractDO;

        //Step 1: 定义关联关系，OrderDO表必须要有distinct()。不查询Srm订单和请购单订单
        JPAQuery<MobileOrderQueryDTO> query = jpaQueryFactory
                .selectDistinct(Projections.constructor(MobileOrderQueryDTO.class, qOrder.shopId, qOrder.id, qOrder.orderNo, qOrder.orderMode, qOrder.orderKind, qOrder.vendorMemberId, qOrder.vendorRoleId, qOrder.vendorMemberName, qOrder.vendorLogo, qOrder.totalAmount, qOrder.buyerInnerStatus, qOrder.outerStatus, qOrder.buyerCommented, qOrder.hasPaid, qOrder.hasDelivered, qOrderContract.contractId, qOrder.promotionStatus, qOrder.groupId, qOrder.canRefund, qOrder.hasRefund))
                .from(qOrder)
                .leftJoin(qOrderProduct).on(qOrder.id.eq(qOrderProduct.order.id))
                .leftJoin(qOrderContract).on(qOrder.id.eq(qOrderContract.order.id))
                .where(qOrder.buyerMemberId.eq(buyerMemberId).and(qOrder.buyerRoleId.eq(buyerRoleId)))
                .where(qOrder.orderKind.ne(OrderSourceKindEnum.SRM.getCode()).and(qOrder.orderKind.ne(OrderSourceKindEnum.REQUISITION.getCode())));

        //Step 2: 构造查询条件
        if (StringUtils.hasLength(keyword)) {
            String pattern = "%".concat(keyword.trim()).concat("%");
            query.where(qOrder.orderNo.like(pattern).or(qOrder.vendorMemberName.like(pattern)).or(qOrderProduct.name.like(pattern)));
        }

        //“待支付订单” 的 状态：“未支付”、“支付失败”、“支付成功，但被供应商确认未到账”
        query.where(qOrder.buyerInnerStatus.eq(BuyerInnerStatusEnum.BUYER_TO_PAY.getCode())
                .or(qOrder.buyerInnerStatus.eq(BuyerInnerStatusEnum.BUYER_PAY_FAIL.getCode()))
                .or(qOrder.buyerInnerStatus.eq(BuyerInnerStatusEnum.BUYER_PAY_SUCCESS.getCode()).and(qOrder.outerStatus.eq(OrderOuterStatusEnum.PAYMENT_NOT_ACCOMPLISH.getCode()))));

        //Step 3: 倒序排序、分页、总数
        long totalCount = query.fetchCount();
        query.orderBy(qOrder.id.desc());
        query.limit(pageSize).offset((current - 1) * pageSize);

        List<MobileOrderQueryDTO> orders = query.fetch();

        //Step 4: 再查询订单商品表
        List<MobileOrderProductQueryDTO> orderProducts = jpaQueryFactory
                .select(Projections.constructor(MobileOrderProductQueryDTO.class,
                        qOrderProduct.order.id,
                        qOrderProduct.id,
                        qOrderProduct.productId,
                        qOrderProduct.skuId,
                        qOrderProduct.stockId,
                        qOrderProduct.priceType,
                        qOrderProduct.logo,
                        qOrderProduct.name,
                        qOrderProduct.category,
                        qOrderProduct.brand,
                        qOrderProduct.spec,
                        qOrderProduct.unit,
                        qOrderProduct.refPrice,
                        qOrderProduct.quantity,
                        qOrderProduct.deliverType,
                        qOrderProduct.address,
                        qOrderProduct.receiver,
                        qOrderProduct.phone
                )).from(qOrderProduct).where(qOrderProduct.order.id.in(orders.stream().map(MobileOrderQueryDTO::getOrderId).collect(Collectors.toList())))
                .fetch();

        //拼接订单商品
        orders.forEach(order -> order.setProducts(orderProducts.stream().filter(orderProduct -> orderProduct.getOrderId().equals(order.getOrderId())).collect(Collectors.toList())));
        return new MobileOrderPageDTO(totalCount, orders);
    }

    /**
     * 查询订单详情
     * @param buyerMemberId 采购会员Id
     * @param buyerRoleId   采购会员角色Id
     * @param orderId       订单Id
     * @return 查询结果
     */
    @Override
    public Wrapper<MobileOrderDetailVO> findMobileOrderDetail(Long buyerMemberId, Long buyerRoleId, Long orderId) {
        QOrderDO qOrder = QOrderDO.orderDO;
        QOrderProductDO qOrderProduct = QOrderProductDO.orderProductDO;
        QOrderPaymentDO qOrderPayment = QOrderPaymentDO.orderPaymentDO;
        QOrderContractDO qOrderContract = QOrderContractDO.orderContractDO;
        QOrderConsigneeDO qOrderConsignee = QOrderConsigneeDO.orderConsigneeDO;
        QOrderInvoiceDO qOrderInvoice = QOrderInvoiceDO.orderInvoiceDO;
        QOrderDeliveryDO qOrderDelivery = QOrderDeliveryDO.orderDeliveryDO;
        QOrderDeliveryProductDO qOrderDeliveryProduct = QOrderDeliveryProductDO.orderDeliveryProductDO;
        QOrderRequirementDO qOrderRequirement = QOrderRequirementDO.orderRequirementDO;

        //Step 1: 查询订单、合同、收货人、发票、其他要求 等一对一关联的表
        MobileOrderDetailVO orderDetail = jpaQueryFactory.from(qOrder).distinct()
                .leftJoin(qOrderContract).on(qOrder.id.eq(qOrderContract.order.id))
                .leftJoin(qOrderConsignee).on(qOrder.id.eq(qOrderConsignee.order.id))
                .leftJoin(qOrderInvoice).on(qOrder.id.eq(qOrderInvoice.order.id))
                .leftJoin(qOrderRequirement).on(qOrder.id.eq(qOrderRequirement.order.id))
                .where(qOrder.id.eq(orderId).and(qOrder.buyerMemberId.eq(buyerMemberId)).and(qOrder.buyerRoleId.eq(buyerRoleId)))
                .transform(GroupBy.groupBy(qOrder.id).as(
                        Projections.constructor(MobileOrderDetailVO.class, qOrder.id, qOrder.orderNo, qOrder.shopId, qOrder.shopName, qOrder.storeId, qOrder.createTime, qOrder.orderMode, qOrder.orderKind, qOrder.promotionStatus, qOrder.groupId, qOrder.hasRefund, qOrder.canRefund, qOrder.digest, qOrder.vendorMemberId, qOrder.vendorRoleId, qOrder.vendorMemberName, qOrder.vendorLogo, qOrder.quoteNo, qOrder.productAmount, qOrder.freight, qOrder.promotionAmount, qOrder.couponAmount, qOrder.deductionAmount, qOrder.taxes, qOrder.totalAmount, qOrder.archiveTime, qOrder.buyerInnerStatus, qOrder.outerStatus, qOrderConsignee.consigneeId, qOrderConsignee.consignee, qOrder.deliverPeriod, qOrderConsignee.provinceName, qOrderConsignee.cityName, qOrderConsignee.districtName, qOrderConsignee.address, qOrderConsignee.phone, qOrderContract.fileName, qOrderContract.url,
                                Projections.constructor(MobileOrderInvoiceDetailVO.class, qOrderInvoice.invoiceKind, qOrderInvoice.invoiceType, qOrderInvoice.title, qOrderInvoice.taxNo, qOrderInvoice.bank, qOrderInvoice.account, qOrderInvoice.address, qOrderInvoice.phone),
                                Projections.constructor(MobileOrderRequirementDetailVO.class, qOrderRequirement.detail)
                        )
                )).getOrDefault(orderId, null);
        if (orderDetail == null) {
            return Wrapper.fail(ResponseCode.ORDER_DOES_NOT_EXIST);
        }

        //Step 2: 查询订单商品
        List<MobileOrderProductDetailVO> orderProductDetails = jpaQueryFactory.select(Projections.constructor(MobileOrderProductDetailVO.class, qOrder.orderKind, qOrder.outerStatus, qOrder.promotionStatus, qOrder.hasPaid, qOrder.hasDelivered, qOrderProduct.id, qOrderProduct.productId, qOrderProduct.skuId, qOrderProduct.priceType, qOrderProduct.logo, qOrderProduct.name, qOrderProduct.category, qOrderProduct.brand, qOrderProduct.spec, qOrderProduct.unit, qOrderProduct.price, qOrderProduct.refPrice, qOrderProduct.quantity, qOrderProduct.deliverType, qOrderProduct.address, qOrderProduct.receiver, qOrderProduct.phone, qOrderProduct.taxRate))
                .from(qOrder)
                .leftJoin(qOrderProduct).on(qOrder.id.eq(qOrderProduct.order.id))
                .where(qOrder.id.eq(orderId)).fetch();

        //Step 3: 查询支付记录
        List<OrderPaymentDO> orderPayments = jpaQueryFactory.select(qOrderPayment).from(qOrderPayment)
                .where(qOrderPayment.order.id.eq(orderId).and(qOrderPayment.payAmount.gt(BigDecimal.ZERO)))
                .fetch();

        //只有最小未支付的次数，才显示“支付”
        Integer payBatchNo = orderPayments.stream().filter(orderPayment -> orderPayment.getBuyerInnerStatus().equals(BuyerInnerStatusEnum.BUYER_TO_PAY.getCode()) || orderPayment.getBuyerInnerStatus().equals(BuyerInnerStatusEnum.BUYER_PAY_FAIL.getCode()) || (orderPayment.getBuyerInnerStatus().equals(BuyerInnerStatusEnum.BUYER_PAY_SUCCESS.getCode()) && orderPayment.getOuterStatus().equals(OrderOuterStatusEnum.PAYMENT_NOT_ACCOMPLISH.getCode()))).map(OrderPaymentDO::getBatchNo).min(Comparator.comparingInt(Integer::intValue)).orElse(0);
        AtomicInteger tag = new AtomicInteger(1);
        List<MobileOrderPaymentDetailVO> orderPaymentDetails = orderPayments.stream().sorted(Comparator.comparingInt(OrderPaymentDO::getBatchNo)).map(payment ->
                new MobileOrderPaymentDetailVO(tag.getAndIncrement(), payment.getId(), payment.getPayTime(), payment.getFundMode(), payBatchNo, payment.getBatchNo(), payment.getPayType(), payment.getPayChannel(), payment.getPayNode(), payment.getBuyerInnerStatus(), payment.getPayRate(), payment.getPayAmount(), payment.getVouchers())).collect(Collectors.toList());

        //Step 4: 查询订单收发货记录（这里要有一个where条件：qOrderDeliveryProduct.orderId.eq(orderId)）
        List<MobileOrderDeliveryDetailVO> deliveryDetails = new ArrayList<>(jpaQueryFactory
                .from(qOrderDelivery).distinct()
                .leftJoin(qOrderDeliveryProduct).on(qOrderDelivery.batchNo.eq(qOrderDeliveryProduct.batchNo))
                .leftJoin(qOrderProduct).on(qOrderDeliveryProduct.orderProductId.eq(qOrderProduct.id))
                .where(qOrderDelivery.order.id.eq(orderId).and(qOrderDeliveryProduct.orderId.eq(orderId)))
                .orderBy(qOrderDelivery.batchNo.asc())
                .transform(GroupBy.groupBy(qOrderDelivery.id).as(
                        Projections.constructor(MobileOrderDeliveryDetailVO.class, qOrderDelivery.createTime, qOrderDelivery.batchNo, qOrderDelivery.logisticsNo, qOrderDelivery.company, qOrderDelivery.receiptTime, qOrderDelivery.receiveBill, qOrderDelivery.selfCode, qOrderDelivery.buyerInnerStatus,
                                GroupBy.list(Projections.constructor(MobileOrderDeliverProductDetailVO.class, qOrderDeliveryProduct.id, qOrderProduct.logo, qOrderDeliveryProduct.name, qOrderDeliveryProduct.category, qOrderDeliveryProduct.brand, qOrderDeliveryProduct.unit, qOrderDeliveryProduct.spec, qOrderDeliveryProduct.delivered, qOrderDeliveryProduct.received)))))
                .values());

        //Step 5: 拼接查询结果，在MobileOrderDetailVO中 字段的setter方法中处理列表和相关字段
        orderDetail.setProducts(orderProductDetails);
        orderDetail.setPayments(orderPaymentDetails);
        orderDetail.setDeliveries(deliveryDetails);

        return Wrapper.success(orderDetail);
    }

    /**
     * 分页查询销售订单
     * @param vendorUserId  登录用户id
     * @param buyerMemberId 采购会员Id
     * @param buyerRoleId   采购会员角色Id
     * @param month         下单月份
     * @param memberName    采购会员名称
     * @param orderType     订单类型
     * @param current       当前页
     * @param pageSize      每页行数
     * @return 查询结果
     */
    @Override
    public MobileOrderPageDTO pageMobileVendorOrders(Long vendorUserId, Long buyerMemberId, List<Long> buyerRoleId, String month, String memberName, Integer orderType, int current, int pageSize) {
        QOrderDO qOrder = QOrderDO.orderDO;
        QOrderProductDO qOrderProduct = QOrderProductDO.orderProductDO;

        //Step 1: 首先分页查询订单表与其一对一关联的表（这样才可以分页）
        JPAQuery<MobileOrderQueryDTO> query = jpaQueryFactory
                .selectDistinct(Projections.constructor(MobileOrderQueryDTO.class, qOrder.shopId, qOrder.id, qOrder.orderNo, qOrder.orderType, qOrder.orderMode, qOrder.orderKind, qOrder.vendorMemberId, qOrder.vendorRoleId, qOrder.vendorMemberName, qOrder.vendorLogo, qOrder.totalAmount, qOrder.buyerInnerStatus, qOrder.outerStatus, qOrder.buyerCommented, qOrder.hasPaid, qOrder.hasDelivered, qOrder.promotionStatus, qOrder.groupId, qOrder.canRefund, qOrder.hasRefund))
                .from(qOrder)
                .where(qOrder.vendorUserId.eq(vendorUserId))
//                .where(qOrder.outerStatus.eq(OrderOuterStatusEnum.ACCOMPLISHED.getCode()))
                .where(qOrder.buyerRoleId.in(buyerRoleId));

        //Step 2: 构造查询条件
        if (buyerMemberId != null) {
            query.where(qOrder.buyerMemberId.eq(buyerMemberId));
        }

        if (orderType == null) {
            query.where(qOrder.orderType.in(OrderTypeEnum.SPOT_PURCHASING.getCode(), OrderTypeEnum.INQUIRY_TO_PURCHASE.getCode(), OrderTypeEnum.CHANNEL_STRAIGHT_MINING.getCode(), OrderTypeEnum.CHANNEL_SPOT.getCode()));
        } else {
            query.where(qOrder.orderType.eq(orderType));
        }

        if (StringUtils.hasLength(memberName)) {
            query.where((qOrder.buyerMemberName.like("%".concat(memberName.trim()).concat("%"))));
        }

        //下单月份
        if (StringUtils.hasLength(month)) {
            query.where(qOrder.submitTime.after(LocalDateTime.parse(month.concat("-01 00:00:00"), OrderServiceContants.DEFAULT_TIME_FORMATTER)));
        }

        //下单月份
        if (StringUtils.hasLength(month)) {
            query.where(qOrder.submitTime.before(LocalDateTime.parse(month.concat("-31 23:59:59"), OrderServiceContants.DEFAULT_TIME_FORMATTER)));
        }

        //Step 3: 倒序排序、分页、总数
        long totalCount = query.fetchCount();
        query.orderBy(qOrder.id.desc());
        query.limit(pageSize).offset((long) (current - 1) * pageSize);

        List<MobileOrderQueryDTO> orders = query.fetch();

        //Step 4: 再查询订单商品表
        List<MobileOrderProductQueryDTO> orderProducts = jpaQueryFactory
                .select(Projections.constructor(MobileOrderProductQueryDTO.class,
                        qOrderProduct.order.id,
                        qOrderProduct.id,
                        qOrderProduct.productId,
                        qOrderProduct.skuId,
                        qOrderProduct.stockId,
                        qOrderProduct.priceType,
                        qOrderProduct.logo,
                        qOrderProduct.name,
                        qOrderProduct.category,
                        qOrderProduct.brand,
                        qOrderProduct.spec,
                        qOrderProduct.unit,
                        qOrderProduct.refPrice,
                        qOrderProduct.quantity,
                        qOrderProduct.deliverType,
                        qOrderProduct.address,
                        qOrderProduct.receiver,
                        qOrderProduct.phone
                )).from(qOrderProduct).where(qOrderProduct.order.id.in(orders.stream().map(MobileOrderQueryDTO::getOrderId).collect(Collectors.toList())))
                .fetch();

        //拼接订单商品
        orders.forEach(order -> order.setProducts(orderProducts.stream().filter(orderProduct -> orderProduct.getOrderId().equals(order.getOrderId())).collect(Collectors.toList())));

        return new MobileOrderPageDTO(totalCount, orders);
    }

    /**
     * 查询销售订单详情
     * @param orderId 订单Id
     * @return 查询结果
     */
    @Override
    public Wrapper<MobileVendorOrderDetailVO> getMobileVendorOrderDetail(Long orderId) {
        QOrderDO qOrder = QOrderDO.orderDO;
        QOrderProductDO qOrderProduct = QOrderProductDO.orderProductDO;
        QOrderPaymentDO qOrderPayment = QOrderPaymentDO.orderPaymentDO;
        QOrderContractDO qOrderContract = QOrderContractDO.orderContractDO;
        QOrderConsigneeDO qOrderConsignee = QOrderConsigneeDO.orderConsigneeDO;
        QOrderInvoiceDO qOrderInvoice = QOrderInvoiceDO.orderInvoiceDO;
        QOrderRequirementDO qOrderRequirement = QOrderRequirementDO.orderRequirementDO;

        //Step 1: 查询订单、合同、收货人、发票、其他要求 等一对一关联的表
        MobileVendorOrderDetailVO orderDetail = jpaQueryFactory.from(qOrder).distinct()
                .leftJoin(qOrderContract).on(qOrder.id.eq(qOrderContract.order.id))
                .leftJoin(qOrderConsignee).on(qOrder.id.eq(qOrderConsignee.order.id))
                .leftJoin(qOrderInvoice).on(qOrder.id.eq(qOrderInvoice.order.id))
                .leftJoin(qOrderRequirement).on(qOrder.id.eq(qOrderRequirement.order.id))
                .where(qOrder.id.eq(orderId))
                .transform(GroupBy.groupBy(qOrder.id).as(
                        Projections.constructor(MobileVendorOrderDetailVO.class, qOrder.id, qOrder.orderNo, qOrder.orderType, qOrder.shopId, qOrder.shopName, qOrder.createTime, qOrder.orderMode, qOrder.orderKind, qOrder.promotionStatus, qOrder.groupId, qOrder.hasRefund, qOrder.canRefund, qOrder.digest, qOrder.buyerMemberId, qOrder.buyerRoleId, qOrder.buyerMemberName, qOrder.vendorMemberId, qOrder.vendorRoleId, qOrder.vendorMemberName, qOrder.vendorLogo, qOrder.quoteNo, qOrder.productAmount, qOrder.freight, qOrder.taxes, qOrder.deductionAmount, qOrder.promotionAmount, qOrder.couponAmount, qOrder.totalAmount, qOrder.archiveTime, qOrder.vendorInnerStatus, qOrder.outerStatus, qOrder.hasPaid, qOrderConsignee.consigneeId, qOrderConsignee.consignee, qOrder.deliverPeriod, qOrderConsignee.provinceName, qOrderConsignee.cityName, qOrderConsignee.districtName, qOrderConsignee.address, qOrderConsignee.phone, qOrderContract.fileName, qOrderContract.url,
                                Projections.constructor(MobileOrderInvoiceDetailVO.class, qOrderInvoice.invoiceKind, qOrderInvoice.invoiceType, qOrderInvoice.title, qOrderInvoice.taxNo, qOrderInvoice.bank, qOrderInvoice.account, qOrderInvoice.address, qOrderInvoice.phone),
                                Projections.constructor(MobileOrderRequirementDetailVO.class, qOrderRequirement.detail))
                )).getOrDefault(orderId, null);
        if (orderDetail == null) {
            return Wrapper.fail(ResponseCode.ORDER_DOES_NOT_EXIST);
        }

        //Step 2: 查询订单商品
        List<MobileOrderProductDetailVO> orderProductDetails = jpaQueryFactory.select(Projections.constructor(MobileOrderProductDetailVO.class, qOrder.orderKind, qOrder.vendorInnerStatus, qOrder.outerStatus, qOrder.promotionStatus, qOrder.hasPaid, qOrder.hasDelivered, qOrderProduct.id, qOrderProduct.productId, qOrderProduct.skuId, qOrderProduct.priceType, qOrderProduct.logo, qOrderProduct.name, qOrderProduct.category, qOrderProduct.brand, qOrderProduct.spec, qOrderProduct.unit, qOrderProduct.price, qOrderProduct.refPrice, qOrderProduct.quantity, qOrderProduct.deliverType, qOrderProduct.address, qOrderProduct.receiver, qOrderProduct.phone, qOrderProduct.taxRate))
                .from(qOrder)
                .leftJoin(qOrderProduct).on(qOrder.id.eq(qOrderProduct.order.id))
                .where(qOrder.id.eq(orderId)).fetch();

        //Step 3: 查询支付记录
        List<OrderPaymentDO> orderPayments = jpaQueryFactory.select(qOrderPayment).from(qOrderPayment)
                .where(qOrderPayment.order.id.eq(orderId).and(qOrderPayment.payAmount.gt(BigDecimal.ZERO)))
                .fetch();

        //只有最小未支付的次数，才显示“支付”
        Integer payBatchNo = orderPayments.stream().filter(orderPayment -> orderPayment.getBuyerInnerStatus().equals(BuyerInnerStatusEnum.BUYER_TO_PAY.getCode()) || orderPayment.getBuyerInnerStatus().equals(BuyerInnerStatusEnum.BUYER_PAY_FAIL.getCode()) || (orderPayment.getBuyerInnerStatus().equals(BuyerInnerStatusEnum.BUYER_PAY_SUCCESS.getCode()) && orderPayment.getOuterStatus().equals(OrderOuterStatusEnum.PAYMENT_NOT_ACCOMPLISH.getCode()))).map(OrderPaymentDO::getBatchNo).min(Comparator.comparingInt(Integer::intValue)).orElse(0);
        AtomicInteger tag = new AtomicInteger(1);
        List<MobileOrderPaymentDetailVO> orderPaymentDetails = orderPayments.stream().sorted(Comparator.comparingInt(OrderPaymentDO::getBatchNo)).map(payment ->
                new MobileOrderPaymentDetailVO(tag.getAndIncrement(), payment.getId(), payment.getPayTime(), payment.getFundMode(), payBatchNo, payment.getBatchNo(), payment.getPayType(), payment.getPayChannel(), payment.getPayNode(), payment.getBuyerInnerStatus(), payment.getOuterStatus(), payment.getPayRate(), payment.getPayAmount(), payment.getVouchers())).collect(Collectors.toList());

//        //Step 4: 查询订单收发货记录（这里要有一个where条件：qOrderDeliveryProduct.orderId.eq(orderId)）
//        List<MobileOrderDeliveryDetailVO> deliveryDetails = new ArrayList<>(jpaQueryFactory
//                .from(qOrderDelivery).distinct()
//                .leftJoin(qOrderDeliveryProduct).on(qOrderDelivery.batchNo.eq(qOrderDeliveryProduct.batchNo))
//                .leftJoin(qOrderProduct).on(qOrderDeliveryProduct.orderProductId.eq(qOrderProduct.id))
//                .where(qOrderDelivery.order.id.eq(orderId).and(qOrderDeliveryProduct.orderId.eq(orderId)))
//                .orderBy(qOrderDelivery.batchNo.asc())
//                .transform(GroupBy.groupBy(qOrderDelivery.id).as(
//                        Projections.constructor(MobileOrderDeliveryDetailVO.class, qOrderDelivery.createTime, qOrderDelivery.batchNo, qOrderDelivery.logisticsNo, qOrderDelivery.company, qOrderDelivery.receiptTime, qOrderDelivery.buyerInnerStatus,
//                                GroupBy.list(Projections.constructor(MobileOrderDeliverProductDetailVO.class, qOrderDeliveryProduct.id, qOrderProduct.logo, qOrderDeliveryProduct.name, qOrderDeliveryProduct.category, qOrderDeliveryProduct.brand, qOrderDeliveryProduct.unit, qOrderDeliveryProduct.spec, qOrderDeliveryProduct.delivered, qOrderDeliveryProduct.received)))
//                        )
//                ).values());

        //Step 5: 拼接查询结果，在MobileOrderDetailVO中 字段的setter方法中处理列表和相关字段
        orderDetail.setProducts(orderProductDetails);
        orderDetail.setPayments(orderPaymentDetails);
//        orderDetail.setDeliveries(deliveryDetails);

        return Wrapper.success(orderDetail);
    }

    /**
     * 订单审核 - 分页查询销售订单
     * @param vendorUserId      登录用户id
     * @param buyerMemberId     采购会员Id
     * @param buyerRoleId       采购会员角色Id
     * @param keyword           订单编号/供应会员
     * @param vendorInnerStatus 供应会员内部状态
     * @param current           当前页
     * @param pageSize          每页行数
     * @return 查询结果
     */
    @Override
    public MobileOrderPageDTO pageMobileVendorValidateOrders(Long vendorUserId, List<Long> buyerMemberId, List<Long> buyerRoleId, String keyword, Integer vendorInnerStatus, int current, int pageSize) {
        QOrderDO qOrder = QOrderDO.orderDO;
        QOrderProductDO qOrderProduct = QOrderProductDO.orderProductDO;

        //Step 1: 首先分页查询订单表与其一对一关联的表（这样才可以分页）。不查询Srm订单和请购单订单
        JPAQuery<MobileOrderQueryDTO> query = jpaQueryFactory
                .selectDistinct(Projections.constructor(MobileOrderQueryDTO.class, qOrder.shopId, qOrder.id, qOrder.orderNo, qOrder.orderType, qOrder.orderMode, qOrder.orderKind, qOrder.vendorMemberId, qOrder.vendorRoleId, qOrder.vendorMemberName, qOrder.vendorLogo, qOrder.totalAmount, qOrder.vendorInnerStatus, qOrder.outerStatus, qOrder.buyerCommented, qOrder.hasPaid, qOrder.hasDelivered, qOrder.promotionStatus))
                .from(qOrder)
                .where(qOrder.buyerRoleId.in(buyerRoleId))
                .where(qOrder.vendorUserId.eq(vendorUserId));

        query.where(qOrder.orderType.in(OrderTypeEnum.SPOT_PURCHASING.getCode(), OrderTypeEnum.INQUIRY_TO_PURCHASE.getCode(), OrderTypeEnum.CHANNEL_STRAIGHT_MINING.getCode(), OrderTypeEnum.CHANNEL_SPOT.getCode()));

        //Step 2: 构造查询条件
        if (StringUtils.hasLength(keyword)) {
            String pattern = "%".concat(keyword.trim()).concat("%");
            query.where(qOrder.orderNo.like(pattern).or(qOrder.buyerMemberName.like(pattern)));
        }

        //供应商内部状态：待提交审核，待审核一级，待审核二级，待确认订单
        if (vendorInnerStatus == null) {
            query.where(qOrder.vendorInnerStatus.in(VendorInnerStatusEnum.VENDOR_TO_SUBMIT_VALIDATE.getCode(), VendorInnerStatusEnum.VENDOR_VALIDATE_GRADE_ONE.getCode(), VendorInnerStatusEnum.VENDOR_VALIDATE_GRADE_TWO.getCode(), VendorInnerStatusEnum.VENDOR_TO_CONFIRM.getCode()));
        } else {
            query.where(qOrder.vendorInnerStatus.eq(vendorInnerStatus));
        }

        //Step 3: 倒序排序、分页、总数
        long totalCount = query.fetchCount();
        query.orderBy(qOrder.id.desc());
        query.limit(pageSize).offset((long) (current - 1) * pageSize);

        List<MobileOrderQueryDTO> orders = query.fetch();

        //Step 4: 再查询订单商品表
        List<MobileOrderProductQueryDTO> orderProducts = jpaQueryFactory
                .select(Projections.constructor(MobileOrderProductQueryDTO.class,
                        qOrderProduct.order.id,
                        qOrderProduct.id,
                        qOrderProduct.productId,
                        qOrderProduct.skuId,
                        qOrderProduct.stockId,
                        qOrderProduct.priceType,
                        qOrderProduct.logo,
                        qOrderProduct.name,
                        qOrderProduct.category,
                        qOrderProduct.brand,
                        qOrderProduct.spec,
                        qOrderProduct.unit,
                        qOrderProduct.refPrice,
                        qOrderProduct.quantity,
                        qOrderProduct.deliverType,
                        qOrderProduct.address,
                        qOrderProduct.receiver,
                        qOrderProduct.phone
                )).from(qOrderProduct).where(qOrderProduct.order.id.in(orders.stream().map(MobileOrderQueryDTO::getOrderId).collect(Collectors.toList())))
                .fetch();

        //拼接订单商品
        orders.forEach(order -> order.setProducts(orderProducts.stream().filter(orderProduct -> orderProduct.getOrderId().equals(order.getOrderId())).collect(Collectors.toList())));

        return new MobileOrderPageDTO(totalCount, orders);
    }
}
